package nckd.wnqjt.tmc.tda.plugin.form;

import java.util.*;
import java.util.stream.Collectors;

import kd.bos.algo.Algo;
import kd.bos.algo.DataSet;
import kd.bos.algo.DataSetBuilder;
import kd.bos.algo.RowMeta;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.db.DB;
import kd.bos.db.DBRoute;
import kd.bos.entity.report.AbstractReportListDataPlugin;
import kd.bos.entity.report.FilterInfo;
import kd.bos.entity.report.FilterItemInfo;
import kd.bos.entity.report.ReportQueryParam;
import kd.bos.orm.ORM;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import org.apache.commons.collections.CollectionUtils;

/**
 * @author husheng
 * @date 2024-11-04 20:08
 * @description 承兑汇票
 */
public class AcceptancebillListDataPlugin extends AbstractReportListDataPlugin {
    @Override
    public DataSet query(ReportQueryParam reportQueryParam, Object o) {
        // 开票登记
        String payablebillSql = "drawercompany.name nckd_drawercompanyname,draweraccount," +
                "drawerbankname nckd_drawerbankname,creditlimit,creditamount nckd_creditamount,amount nckd_amount," +
                "promisrate nckd_promisrate,issuedate nckd_issuedate,draftbillexpiredate nckd_draftbillexpiredate";
        QFilter filter = this.buildFilter(reportQueryParam);
        DataSet cdmPayablebill = QueryServiceHelper.queryDataSet(this.getClass().getName(), "cdm_payablebill", payablebillSql, filter.toArray(), null);

        // 授信类别  SX0003 银行承兑汇票
        DynamicObject credittype = BusinessDataServiceHelper.loadSingle("cfm_credittype", new QFilter[]{new QFilter("number", QCP.equals, "SX0003")});

        // 授信额度管理
        String creditlimitSql = "id,entry_type.t_credittype,entry_type.t_totalamt";
        QFilter qFilter = new QFilter("status", QCP.equals, "C")
                .and("enddate", QCP.large_than, this.getCurrentDate());
        DataSet cfmCreditlimit = QueryServiceHelper.queryDataSet(this.getClass().getName(), "cfm_creditlimit", creditlimitSql, qFilter.toArray(), null);

        ORM orm = ORM.create();
        DynamicObjectCollection creditlimit = orm.toPlainDynamicObjectCollection(cfmCreditlimit);

        // 排除授信类别不是银行承兑汇票的数据
        List<DynamicObject> collect = creditlimit.stream().filter(t -> {
            if (t.getLong("entry_type.t_credittype") != 0) {
                // 授信类别 多选基础资料
                StringBuffer stringBuffer = new StringBuffer("select t.fbasedataid from t_cfm_creditlimit_detai_d t where t.fentryid = ?");
                DataSet dataSet = DB.queryDataSet("t_cfm_creditlimit_detai_d", new DBRoute("tmc"), stringBuffer.toString(), new Object[]{t.getLong("entry_type.t_credittype")});
                DynamicObjectCollection dynamicObjects = orm.toPlainDynamicObjectCollection(dataSet);
                long fbasedataid = dynamicObjects.get(0).getLong("fbasedataid");
                if (fbasedataid == credittype.getLong("id")) {
                    return true;
                }
            }

            return false;
        }).collect(Collectors.toList());

        DynamicObjectCollection dynamicObjects = new DynamicObjectCollection();
        dynamicObjects.addAll(collect);

        cfmCreditlimit = buildDataByObjCollection("algoKey", cfmCreditlimit.getRowMeta().getFields(), dynamicObjects);

        DataSet dataSet = cdmPayablebill.leftJoin(cfmCreditlimit).on("creditlimit", "id").select(cdmPayablebill.getRowMeta().getFieldNames(), new String[]{"entry_type.t_totalamt as nckd_t_totalamt"}).finish();

        dataSet = dataSet.select(new String[]{"nckd_drawercompanyname", "nckd_drawerbankname", "(nckd_creditamount / 10000) nckd_creditamount",
                "(nckd_amount / 10000) nckd_amount", "nckd_promisrate", "nckd_issuedate", "nckd_draftbillexpiredate", "(nckd_t_totalamt / 10000) nckd_t_totalamt",
                "(nckd_amount / 10000 - nckd_amount * nckd_promisrate / 100 / 10000) nckd_expireamount",
                "(nckd_amount * nckd_promisrate / 100 / 10000) nckd_suretyamount", "1 nckd_seq"});

        // 分组，生成小计行
        DataSet dataSetSum = dataSet.groupBy(new String[]{"nckd_drawercompanyname"}).sum("nckd_creditamount").sum("nckd_amount").sum("nckd_t_totalamt").sum("nckd_expireamount").sum("nckd_suretyamount").finish();
        dataSetSum = dataSetSum.select(new String[]{"nckd_drawercompanyname", "'小计' as nckd_drawerbankname", "nckd_creditamount",
                "nckd_amount", "null nckd_promisrate", "null nckd_issuedate", "null nckd_draftbillexpiredate", "nckd_t_totalamt",
                "nckd_expireamount", "nckd_suretyamount", "2 nckd_seq"});

        // 将原dataSet与小计之后的dataSet用union进行合并
        DataSet dataSetUnion = dataSet.union(dataSetSum).orderBy(new String[]{"nckd_drawercompanyname", "nckd_seq"});

        // 生成合计
        DataSet ds = dataSetSum.copy().groupBy(null).sum("nckd_creditamount").sum("nckd_amount").sum("nckd_t_totalamt").sum("nckd_expireamount").sum("nckd_suretyamount").finish();
        ds = ds.select(new String[]{"'-' as nckd_drawercompanyname", "'合计' as nckd_drawerbankname", "nckd_creditamount",
                "nckd_amount", "null nckd_promisrate", "null nckd_issuedate", "null nckd_draftbillexpiredate", "nckd_t_totalamt",
                "nckd_expireamount", "nckd_suretyamount", "3 nckd_seq"});

        DataSet finish = dataSetUnion.union(ds);
        return finish;
    }

    private QFilter buildFilter(ReportQueryParam reportQueryParam) {
        // 查询条件
        FilterInfo filterInfo = reportQueryParam.getFilter();

        //筛选出 筛选器传入的ids
        Map<String, Object> customParam = reportQueryParam.getCustomParam();
        List<Long> longList = null;
        if (!customParam.isEmpty()) {
            List<String> list = (ArrayList<String>) customParam.get("id");
            if (CollectionUtils.isNotEmpty(list)) {
                longList = list.stream().map(e -> Long.valueOf(e)).collect(Collectors.toList());
            }
        }


        QFilter qFilter = new QFilter("rptype", QCP.equals, "paybill")
                .and("draftbilltype.number", QCP.in, new String[]{"102", "104", "CDMT-79A2C33B"})
                .and("billstatus", QCP.equals, "C")
                .and("draftbillstatus", QCP.equals, "registered")
                .and("draftbilltranstatus", QCP.equals, "success")
                .and("draftbillexpiredate", QCP.large_equals, this.getCurrentDate());

        // 单位
        FilterItemInfo company = filterInfo.getFilterItem("nckd_company");
        // 出票银行
        FilterItemInfo drawerbank = filterInfo.getFilterItem("nckd_drawerbank");

        // 单位
        if (company.getValue() != null) {
            qFilter = qFilter.and(new QFilter("drawercompany", QCP.in, ((DynamicObjectCollection) company.getValue())
                    .stream()
                    .map(obj -> obj.getLong("id"))
                    .collect(Collectors.toList())));
        }
        // 出票银行
        if (drawerbank.getValue() != null) {
            qFilter = qFilter.and(new QFilter("draweraccount.bank", QCP.in, ((DynamicObjectCollection) drawerbank.getValue())
                    .stream()
                    .map(obj -> obj.getLong("id"))
                    .collect(Collectors.toList())));
        }

        if (CollectionUtils.isNotEmpty(longList)) {
            qFilter = qFilter.and("id", QCP.in, longList);
        }
        return qFilter;
    }

    //DynamicObjectCollection 转换为 DataSet 方法
    public DataSet buildDataByObjCollection(String algoKey, kd.bos.algo.Field[] rowFields, DynamicObjectCollection objCollection) {
        DataSetBuilder dataSetBuilder = Algo.create(algoKey + ".emptyFields")
                .createDataSetBuilder(new RowMeta(rowFields));
        for (DynamicObject arObj : objCollection) {
            Object[] rowData = new Object[rowFields.length];
            for (int i = 0; i < rowFields.length; i++) {
                kd.bos.algo.Field field = rowFields[i];
                rowData[i] = arObj.get(field.getName());
            }
            dataSetBuilder.append(rowData);
        }
        return dataSetBuilder.build();
    }

    private Date getCurrentDate() {
        Calendar cal = new GregorianCalendar();
//        cal.set(11, 0);
//        cal.set(12, 0);
//        cal.set(13, 0);
//        cal.set(14, 0);
        return cal.getTime();
    }
}
